/*
 * Copyright 2014 Alibaba.com All right reserved. This software is the
 * confidential and proprietary information of Alibaba.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Alibaba.com.
 */
package com.alibaba.wallstreet.uitls;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.springframework.aop.SpringProxy;
import org.springframework.util.ClassUtils;

/**
 * 类ClassUtil.java的实现描述：TODO 类实现描述
 * 
 * @author moxian.zl 2014-3-4 上午10:24:56
 */
public class ClassUtil extends ClassUtils {

    public static Class<?> getCollectionActualClass(Collection<?> collection) {
        Type[] types = getClassActualType(collection);
        if (types.length == 0) {
            return null;
        }
        return (Class<?>) types[0];
    }

    public static Class<?> getListFieldActualClass(Field field) {
        if (!List.class.isAssignableFrom(field.getType())) {
            throw new IllegalArgumentException("Field must List or assignable from List");
        }
        return (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
    }

    /**
     * 获得泛型类中实际类型
     * 
     * @param o
     * @return
     */
    public static Type[] getClassActualType(Object o) {
        return ((ParameterizedType) o.getClass().getGenericSuperclass()).getActualTypeArguments();
    }

    /**
     * 用于获得泛型接口中的实际类型
     * 
     * @param clazz 实现泛型接口的类
     * @param interfaceClass 泛型接口类
     * @return
     */
    public static Type[] getInterfaceActualType(Class<?> clazz, Class<?> interfaceClass) {
        // while (isSpringAopClass(clazz)) {
        // clazz = clazz.getSuperclass();
        // }

        for (Type type : clazz.getGenericInterfaces()) {
            if (type instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                if (parameterizedType.getRawType() == interfaceClass) {
                    return parameterizedType.getActualTypeArguments();
                }
            }
        }
        return null;
    }

    public static boolean isSpringAopClass(Class<?> clazz) {
        if (clazz.getSuperclass().isAssignableFrom(Proxy.class)) {
            return false;
        }
        for (Class<?> cls : clazz.getInterfaces()) {
            if (cls.isAssignableFrom(SpringProxy.class)) {
                return true;
            }
        }
        return false;
    }

    public static List<Field> getAllFields(Class<?> clazz) {
        List<Field> result = new ArrayList<Field>();
        Collections.addAll(result, clazz.getDeclaredFields());
        if (clazz != Object.class) {
            List<Field> parentFields = getAllFields(clazz.getSuperclass());
            result.addAll(parentFields);
        }
        return result;
    }

    public static boolean isPrimitiveClass(Class<?> clazz) {
        if (clazz.isPrimitive()) {
            return true;
        }
        try {
            return ((Class<?>) clazz.getField("TYPE").get(null)).isPrimitive();
        } catch (Exception e) {
            return false;
        }
    }

    public static String getCallerMethodName(int methodCount) {
        try {
            return Thread.currentThread().getStackTrace()[methodCount].getMethodName();
        } catch (Exception e) {
            return "";
        }
    }

}
